package com.assets.util;

/**
 * @Author 蒋剑华
 * @Description TODO 用来生成唯一不重复的id，用的雪花算法
 * @Date 14:34 2023/9/15
 * @Param 
 * @return 
 * @detail 
 **/

public class IdWorkerUtil {

    private static final long EPOCH = 1628000000000L;
    private static final long MAX_MACHINE_ID = 1023L;
    private static final long MAX_SEQUENCE = 4095L;

    private static volatile IdWorkerUtil instance;

    private long machineId = 0L;
    private long sequence = 0L;
    private long lastTimestamp = -1L;

//    private int idLength = 19; // 默认生成19位ID

    private IdWorkerUtil(long machineId) {
        if (machineId < 0 || machineId > MAX_MACHINE_ID) {
            throw new IllegalArgumentException("Machine ID must be between 0 and " + MAX_MACHINE_ID);
        }
        this.machineId = machineId;
    }

    public static IdWorkerUtil getInstance(long machineId) {
        if (instance == null) {
            synchronized (IdWorkerUtil.class) {
                if (instance == null) {
                    instance = new IdWorkerUtil(machineId);
                }
            }
        }
        return instance;

    }

    public synchronized String generateUniqueId(int idLength) {
        long timestamp = System.currentTimeMillis();

        if (timestamp < lastTimestamp) {
            try {
                Thread.sleep(lastTimestamp - timestamp);
                timestamp = System.currentTimeMillis();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        if (timestamp == lastTimestamp) {
            sequence = (sequence + 1) & MAX_SEQUENCE;
            if (sequence == 0) {
                timestamp = tilNextMillis(timestamp);
            }
        } else {
            sequence = 0L;
        }

        lastTimestamp = timestamp;

        long uniqueId = ((timestamp - EPOCH) << 22) | (machineId << 12) | sequence;

        String idString = String.valueOf(uniqueId);

        if (idString.length() < idLength) {
            if (idString.charAt(0) == '0') {
                idString = "1" + idString.substring(1);
            }

            while (idString.length() < idLength) {
                idString = "1" + idString;
            }
        } else if (idString.length() > idLength) {
            idString = idString.substring(idString.length() - idLength);
        }

        return idString;
    }

    private long tilNextMillis(long timestamp) {
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }



    // 私有化构造函数，防止被实例化
    private IdWorkerUtil() {
    }
}




